--[[
    @brief    simple webview host window impl
    @author   senpingtian
    @date     2019-08-14
--]]

simple_web_host_window = {
    host_wnd_data = {};
    kDarkBtnBk = "ONEIMAGE:client_social\\close_btn_normal.png;Stretch;0;";
    kDarkBtnBkHover = "ONEIMAGE:client_social\\close_btn_hover.png;Stretch;0;";
    kCloseBtnMargin = { -1, 10, 12, -1 }; -- -1:ignore
    kRoundSetNormal = "ROUNDRECT:4,4";
    kRoundSetFailedPage = "ROUNDRECT:4,4";
    kRoundSetZero = "ROUNDRECT:0,0";  -- 直角
};

function simple_web_host_window:init()
    base_utility.log("[simple_web_host_window]init.");
    comm_center.reg_service("i_service_show_simple_web_window", "simple_web_host_window:show");
    comm_center.reg_service("i_service_close_simple_web_window", "simple_web_host_window:close_svr");
end;

function simple_web_host_window:show(param)
    base_utility.log("[simple_web]show " .. base_utility.table_to_json(param));
    local temp_data = self:find_window_by_param(param);
    if nil ~= temp_data and
       nil ~= temp_data.dialog_ptr then
        base_utility.log("[simple_web][show]alread exist, dialog_id:" ..
                tostring(temp_data.dialog_id));
        if true == param.reload then
            base_utility.log("[simple_web]reload");
            self:load_page(temp_data.webctrl_id, param);
        else
            base_utility.log("[simple_web][show]BringToTop");
            temp_data.dialog_ptr:BringToTop();
            if true == param.modal then
                ui_utility.do_fake_modal_by_id(dialog_id);
            end
        end
        if nil ~= param.caption then
            ui_utility.setproperty_by_id(temp_data.dialog_id, "Caption", param.caption);
        end
        return temp_data.dialog_id;
    end

    local ptr = self:create_view_window(param);
    local dialog_id = Tenio.INVALID_CONTROLID;
    if ptr ~= nil then
        dialog_id = ptr:GetControlID();
        if nil ~= param.caption then
            ui_utility.setproperty_by_id(dialog_id, "Caption", param.caption);
        end

        if ptr:IsVisible() == TRUE then
            base_utility.log("[simple_web][show]visible is TRUE, BringToTop");
            ptr:BringToTop();
            return dialog_id;
        elseif false == param.show_loading_page then
            base_utility.log("[simple_web][show]show_loading_page is false");
            return dialog_id;
        end
        --base_utility.log("[simple_web][show]Show and BringToTop");
        --ptr:Show(TRUE);
        --ptr:BringToTop();
        if true == param.modal then
            ui_utility.do_fake_modal_by_id(dialog_id);
        end
    else
        base_utility.log("[simple_web_host_window][show]ptr is nil", true);
    end
    return dialog_id;
end;

function simple_web_host_window:close_svr(param)
    if nil == param or Tenio.INVALID_CONTROLID == param.id then
        return;
    end
    self:close(nil, param.id);
end;

function simple_web_host_window:hide(uilib, ctrl_id)
    local dialog_id = ctrl_id;
    local wnd_data = self:find_window_by_id(ctrl_id);
    if nil == wnd_data then
        dialog_id = ui_utility.get_ctrl_parent_id(ctrl_id);
        wnd_data = self:find_window_by_id(dialog_id);
    end
    if nil ~= wnd_data and nil ~= wnd_data.dialog_ptr then
        wnd_data.dialog_ptr:Show(FALSE);
    end
end;

function simple_web_host_window:close(uilib, ctrl_id)
    base_utility.log("[simple_web]close " .. tostring(ctrl_id));
    local dialog_id = ctrl_id;
    local wnd_data = self:find_window_by_id(ctrl_id);
    if nil == wnd_data then
        dialog_id = ui_utility.get_ctrl_parent_id(ctrl_id);
        wnd_data = self:find_window_by_id(dialog_id);
    end
    if nil ~= wnd_data then
        dialog_id = wnd_data.dialog_id;
        wnd_data.dialog_ptr:Show(FALSE);
        if nil ~= wnd_data.param and true == wnd_data.param.modal then
            ui_utility.end_fake_modal_by_id(dialog_id);
        end
        layout_mgr.delay_remove_ctrl(dialog_id);
        if nil ~= wnd_data.param and 
            nil ~= wnd_data.param.close_window and
            "" ~= wnd_data.param.close_window then
            comm_center.call_service(wnd_data.param.close_window, { id = dialog_id });
        end
        self.host_wnd_data[dialog_id] = nil;
    end
end;

function simple_web_host_window:create_view_window(param)
    base_utility.log("[simple_web]create_view_window");
    local temp_data = self:find_window_by_param(param);
    if nil ~= temp_data then
        base_utility.log("[simple_web][create_view_window]alread exist, " ..
                tostring(temp_data.dialog_id));
        return temp_data.dialog_ptr;
    end

    local wnd_data = {};
    if param.has_border == nil or param.has_border == false then
        wnd_data.dialog_id = layout_mgr.restore_layout_multi("WebHostWnd.tpf");
    else
        wnd_data.dialog_id = layout_mgr.restore_layout_multi("WebHostWndWithBorder.tpf");
    end;
    if Tenio.INVALID_CONTROLID == wnd_data.dialog_id then
        base_utility.log("[simple_web_host_window]restore layout failed.", true);
        return;
    end

    if false == param.resizable then
        ui_utility.setproperty_by_id(wnd_data.dialog_id, "SizeBox", "false");
    end

    wnd_data.dialog_ptr = ui_utility.get_ctrl_ptr_by_id(wnd_data.dialog_id);
    if nil == wnd_data.dialog_ptr then
        base_utility.log("[simple_web_host_window]get window handle failed.", true);
        return;
    end

    local webctrl_id = ui_utility.get_ctrl_id_by_path(wnd_data.dialog_id, "webCtn");
    if Tenio.INVALID_CONTROLID == webctrl_id then
        base_utility.log("[simple_web_host_window]get webctrl id failed.", true);
        return;
    end
    wnd_data.webctrl_id = webctrl_id;

    local width = param.width or 0;
    local height = param.height or 0;

    if 0 == width or 0 == height then
        wnd_data.dialog_ptr:Maximize();
    else
        ui_utility.setproperty_by_id(wnd_data.dialog_id, "Width", tostring(width));
        ui_utility.setproperty_by_id(wnd_data.dialog_id, "Height", tostring(height));
        wnd_data.dialog_ptr:MoveToCenter();
    end

    if true == param.region_set_zero then
        base_utility.log("[simple_web_host_window]set kRoundSetZero");
        ui_utility.setproperty_by_id(wnd_data.dialog_id, "RegionSet", self.kRoundSetZero);
        ui_utility.setproperty_by_id(wnd_data.webctrl_id, "RegionSet", self.kRoundSetZero);
    end

    if param.always_on_top then
        ui_utility.setproperty_by_id(wnd_data.dialog_id, "AlwaysOnTop", "true");
    else
        ui_utility.setproperty_by_id(wnd_data.dialog_id, "AlwaysOnTop", "false");
    end

    ui_utility.setproperty_by_id(webctrl_id, "OnNavigateFailed", 
                                "simple_web_host_window:on_web_navigate_failed");
    ui_utility.setproperty_by_id(webctrl_id, "OnNavigateComplete", 
                                "simple_web_host_window:on_web_navigate_complete");
    ui_utility.setproperty_by_id(webctrl_id, "OnJsCallback",
                                "simple_web_host_window:on_js_callback");
    local close_btn_dlg_ctn = ui_utility.get_ctrl_id_by_path(wnd_data.dialog_id, "ctnCloseBtn");
    base_utility.log("[simple_web][create]got close_btn_dlg_ctn " ..
            tostring(close_btn_dlg_ctn))
    if Tenio.INVALID_CONTROLID == close_btn_dlg_ctn then
        base_utility.log("[simple_web_host_window]get close btn dlg id failed.", true);
        return;
    end

    if param.title_in_web == true then
        ui_utility.show_ctrl(close_btn_dlg_ctn, false);
    else
        ui_utility.show_ctrl(close_btn_dlg_ctn, true);
    end
    wnd_data.dialog_close_btn_id = close_btn_dlg_ctn;

    local close_btn_id = ui_utility.get_ctrl_id_by_path(close_btn_dlg_ctn, "btnClose");
    if Tenio.INVALID_CONTROLID == close_btn_id then
        base_utility.log("[simple_web_host_window]get close btn id failed.", true);
        return;
    end


    if true == param.dark_close_btn then
        ui_utility.setproperty_by_id(close_btn_id, "Background", self.kDarkBtnBk);
        ui_utility.setproperty_by_id(close_btn_id, "BackgroundHover", self.kDarkBtnBkHover);
        ui_utility.setproperty_by_id(close_btn_id, "BackgroundPressed", self.kDarkBtnBk);
    end

    ui_utility.setproperty_by_id(close_btn_id, "OnClick", 
                                "simple_web_host_window:close");

    self:load_page(webctrl_id, param);

    wnd_data.param = param;

    self.host_wnd_data[wnd_data.dialog_id] = wnd_data;

    return wnd_data.dialog_ptr;
end;

function simple_web_host_window:load_page(wc_id, param)
    base_utility.log("[simple_web]load_page");
    local url = param.url or "";
    if true == param.use_ptlogin then
        url = web_utility.make_login_status_url(url, login_model.main_uin);
    end;

    local webctrl_ptr = ui_utility.get_ctrl_ptr_by_id(wc_id);
    if nil == webctrl_ptr then
        base_utility.log("[simple_web][load_page]webctrl_ptr is nil");
        return;
    end
    local url_str, str_holder = U8toCUIStr(url);
    webctrl_ptr:Navigate(url_str);
end;

function simple_web_host_window:create_params_equals(lp, rp)
    if nil == lp or nil == rp then 
        return false;
    end

    if nil == lp.url or nil == rp.url then
        return false;
    end

    local jump_mode = false;
    local jump_url = LoadStr("PTLOGIN2_URL");
    local l_url = lp.url;
    local r_url = rp.url;
    -- 只比较不带参数的目标跳转链接地址
    if nil ~= string.find(rp.url, jump_url, 1, true) then
        r_url = string.match(rp.url, "u1=([^?]+)");
    else
        r_url = string.match(r_url, "([^?]+)");
    end
    if nil ~= string.find(lp.url, jump_url, 1, true) then
        l_url = string.match(lp.url, "u1=([^?]+)");
    else
        l_url = string.match(l_url, "([^?]+)");
    end

    return l_url == r_url;
end;

function simple_web_host_window:find_window_by_param(param)
    for k, v in pairs(self.host_wnd_data) do
        if nil ~= v.param and self:create_params_equals(v.param, param) then
            return v;
        end
    end
    return nil;
end;

function simple_web_host_window:find_window_by_id(wnd_id)
    for k, v in pairs(self.host_wnd_data) do
        if v.dialog_id == wnd_id or v.dialog_close_btn_id == wnd_id then
            return v;
        end
    end
    return nil;
end;

function simple_web_host_window:find_window_by_webctrl_id(ctrl_id)
    for k, v in pairs(self.host_wnd_data) do
        if v.webctrl_id == ctrl_id then
            return v;
        end
    end
    return nil;
end;

function simple_web_host_window:on_web_navigate_failed(uilib, page_url)
    base_utility.log("[simple_web_host_window]on_web_navigate_failed " .. tostring(page_url),
            true);
    local param = { url = page_url };
    local config = self:find_window_by_param(param);
    if nil ~= config then
        if Tenio.INVALID_CONTROLID ~= config.dialog_close_btn_id then
            base_utility.log("[simple_web][on_web_navigate_failed]hide close button " ..
                tostring(config.dialog_close_btn_id));
            ui_utility.show_ctrl(config.dialog_close_btn_id, false);
            --ui_utility.setproperty_by_id(config.dialog_id, "RegionSet", self.kRoundSetFailedPage);
            --config.round_set_changed = true;
        else
            base_utility.log("[simple_web][on_web_navigate_failed]dialog_close_btn_id invalid:" ..
                tostring(config.dialog_close_btn_id),
                    true);
        end
        param = config.param;
        config.dialog_ptr:Show(TRUE);
        config.dialog_ptr:BringToTop();
        if true == param.modal then
            ui_utility.do_fake_modal_by_id(config.dialog_id);
        end
    else
        base_utility.log("[simple_web_host_window][on_web_navigate_failed]config is nil",
                true);
    end
end;

function simple_web_host_window:on_web_navigate_complete(uilib, page_url)
    base_utility.log("[simple_web_host_window]on_web_navigate_complete " ..
            tostring(page_url));
    local param = { url = page_url };
    local config = self:find_window_by_param(param);
    if nil ~= config and nil ~= config.param then
        param = config.param;
        config.dialog_ptr:Show(TRUE);
        config.dialog_ptr:BringToTop();
        if true == param.modal then
            ui_utility.do_fake_modal_by_id(config.dialog_id);
        end
        if config.round_set_changed then
            ui_utility.setproperty_by_id(config.dialog_id, "RegionSet", self.kRoundSetNormal);
            config.round_set_changed = nil;
        end
    else
        base_utility.log("[simple_web_host_window][on_web_navigate_complete]config is nil",
                true);
    end
end;

function simple_web_host_window:on_pos_changed(uilib, ctrl_id)
    local data = self:find_window_by_id(ctrl_id);
    if nil == data then
        return;
    end
    local close_btn_ptr = ui_utility.get_ctrl_ptr_by_id(data.dialog_close_btn_id);
    if nil == close_btn_ptr then
        return;
    end
    local rc_host = data.dialog_ptr:GetRectEx(FALSE, TRUE);
    local rc_btn = close_btn_ptr:GetRectEx(FALSE, TRUE);
    local ww, wh = rc_host.right - rc_host.left, rc_host.bottom - rc_host.top;
    local ww_btn, wh_btn = rc_btn.right - rc_btn.left, rc_btn.bottom - rc_btn.top;
    rc_btn.right = ww - self.kCloseBtnMargin[3];
    rc_btn.left = rc_btn.right - ww_btn;
    rc_btn.top = 0 + self.kCloseBtnMargin[2];
    rc_btn.bottom = rc_btn.top + wh_btn;
    local tpf_ui = base_utility.get_component_adapter("ITpf_ui", "ierd_tgp.tpf_ui.GetTPFUI();");
    if nil ~= tpf_ui then
        tpf_ui:DPIScale(rc_btn);
    end
    close_btn_ptr:Move(rc_btn);
end;

function simple_web_host_window:delay_close_window(user_data)
    base_utility.remove_interval("simple_web_host_window:delay_close_window", user_data);
    if nil == user_data then
        return;
    end
    self:close(nil, user_data);
end;

function simple_web_host_window:on_js_callback(uilib, func_name, json_str, ctrl_id)
    base_utility.log("[simple_web_host_window]on_js_callback, " ..
        ", func_name:" .. tostring(func_name) ..
        ", ctrl_id:" .. tostring(ctrl_id));
    local wnd_param = self:find_window_by_webctrl_id(ctrl_id);
    if nil == wnd_param then
        base_utility.log("[simple_web_host_window][on_js_callback]wnd_param nil, " ..
                ", func_name:" .. tostring(func_name) ..
                ", ctrl_id:" .. tostring(ctrl_id));
        return;
    end
    -- 兼容各页面现有关闭逻辑；后面建议规范页面调用关闭弹框的方式，统一用close_dlg。
    if func_name == "jc_close_window" then
        local delay_close = false;
        if nil == json_str or "" == json_str then
            json_str = "{}";
        end
        local params = base_utility.json_to_table(json_str);
        if params.command == "call_service" then
            base_utility.log("[simple_web_host_window][on_js_callback]");
            local service_name = params.name or "";
            local service_params = params.params or {};
            comm_center.call_service(service_name, service_params);
            delay_close = true;
        end
        if not delay_close then
            base_utility.log("[simple_web_host_window][on_js_callback]close " ..
                    tostring(wnd_param.dialog_id));
            self:close(uilib, wnd_param.dialog_id);
        else
            base_utility.log("[simple_web_host_window][on_js_callback]hide " ..
                    tostring(wnd_param.dialog_id));
            self:hide(uilib, wnd_param.dialog_id);
            base_utility.add_interval("simple_web_host_window:delay_close_window", 5000,
                                       wnd_param.dialog_id);
        end
    elseif func_name == "close" then
        self:close(uilib, wnd_param.dialog_id);
    end
end


simple_web_host_window.init();